#pragma once

#include <boostext/queue/queue.hpp>
#include <boostext/signal.hpp>

#include "exports.hpp"
#include "stream.hpp"




namespace logger
{
	/**
	 * The memorystream implements the logger::stream interface and acts as intermediate
	 * storage. Since a stream must be multithreaded by definition, entries are stored
	 * in a queue and can be retrieved by calling pop_all.
	 *
	 * Usually there should be some end-storage that actually stores entries and uses the memorystream
	 * to synchronize logging from different threads (so the actual storage doesn't need to
	 * implement that).
	 */
	class LOGGER_API memorystream
		: public stream
	{
	public:

		static const QString SERVICE_NAME;

		typedef boost::shared_ptr<memorystream>         ptr;
		typedef boost::shared_ptr<const memorystream>   const_ptr;
		typedef boostext::queue<entry>                  entry_queue;
		typedef entry_queue::_List_Ty                   auto_list;
		typedef entry_queue::unbuffered_writer          writer;
		typedef entry_queue::unbuffered_reader          reader;
		typedef boost::signals2::signal<void()>         notify;

	private:

		/// This signal is emitted whenever there are pending entries.
		notify        m_pending;

		entry_queue   m_queue;
		writer        m_writer;
		reader        m_reader;

	public:

		memorystream(boost::shared_ptr<const services::provider> provider);



		/**
		 * Log an entry to a certain device (called stream)
		 * The behaviour is to be implemented by subclasses to log
		 * to a specific device.
		 */
		virtual stream &operator<<(const entry&);

		/**
		 * @returns all log entries from the memory stream
		 */
		auto_list pop_all();



		boostext::connector<notify>   pending;
	};
	///////////////////////////////////////////////////////////////////////////////////////////////
}
///////////////////////////////////////////////////////////////////////////////////////////////////
